﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Threading;

namespace Cyclops.Core.Resource
{
    /// <summary>
    /// An adaptor between Dispatcher and ISynchronizeInvoke
    /// </summary>
    public class SynchronizeInvokeImpl : ISynchronizeInvoke
    {
        private readonly Dispatcher dispatcher;

        public SynchronizeInvokeImpl(Dispatcher dispatcher)
        {
            this.dispatcher = dispatcher;
        }

        #region Implementation of ISynchronizeInvoke

        /// <summary>
        /// Asynchronously executes the delegate on the thread that created this object.
        /// </summary>
        /// <returns>
        /// An <see cref="T:System.IAsyncResult"/> interface that represents the asynchronous operation started by calling this method.
        /// </returns>
        /// <param name="method">A <see cref="T:System.Delegate"/> to a method that takes parameters of the same number and type that are contained in <paramref name="args"/>. </param><param name="args">An array of type <see cref="T:System.Object"/> to pass as arguments to the given method. This can be null if no arguments are needed. </param>
        public IAsyncResult BeginInvoke(Delegate method, object[] args)
        {
            dispatcher.BeginInvoke(method, args);
            return null;
        }

        /// <summary>
        /// Waits until the process started by calling <see cref="M:System.ComponentModel.ISynchronizeInvoke.BeginInvoke(System.Delegate,System.Object[])"/> completes, and then returns the value generated by the process.
        /// </summary>
        /// <returns>
        /// An <see cref="T:System.Object"/> that represents the return value generated by the asynchronous operation.
        /// </returns>
        /// <param name="result">An <see cref="T:System.IAsyncResult"/> interface that represents the asynchronous operation started by calling <see cref="M:System.ComponentModel.ISynchronizeInvoke.BeginInvoke(System.Delegate,System.Object[])"/>. </param>
        public object EndInvoke(IAsyncResult result)
        {
            throw new NotSupportedException();
        }

        /// <summary>
        /// Synchronously executes the delegate on the thread that created this object and marshals the call to the creating thread.
        /// </summary>
        /// <returns>
        /// An <see cref="T:System.Object"/> that represents the return value from the delegate being invoked, or null if the delegate has no return value.
        /// </returns>
        /// <param name="method">A <see cref="T:System.Delegate"/> that contains a method to call, in the context of the thread for the control. </param><param name="args">An array of type <see cref="T:System.Object"/> that represents the arguments to pass to the given method. This can be null if no arguments are needed. </param>
        public object Invoke(Delegate method, object[] args)
        {
            return dispatcher.Invoke(method, args);
        }

        /// <summary>
        /// Gets a value indicating whether the caller must call <see cref="M:System.ComponentModel.ISynchronizeInvoke.Invoke(System.Delegate,System.Object[])"/> when calling an object that implements this interface.
        /// </summary>
        /// <returns>
        /// true if the caller must call <see cref="M:System.ComponentModel.ISynchronizeInvoke.Invoke(System.Delegate,System.Object[])"/>; otherwise, false.
        /// </returns>
        public bool InvokeRequired { get { return dispatcher.Thread != Thread.CurrentThread; } }

        #endregion
    }
}
